package com.lp.mgt.services.impls;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lp.mgt.configs.shiro.ShiroRealm;
import com.lp.mgt.entities.Department;
import com.lp.mgt.entities.Menu;
import com.lp.mgt.entities.User;
import com.lp.mgt.mappers.MenuMapper;
import com.lp.mgt.services.MenuService;
import com.lp.mgt.utils.ShrioUtil;
import com.lp.mgt.utils.TreeUtils;
import com.lp.mgt.utils.UUIDUtil;

@Service
@Transactional
public class MenuServiceImpl implements MenuService {
	@Autowired
	private MenuMapper menuMapper;
	
	
/*	@Override
	public List<Menu> selectMenusByUser(User user) {
        List<Menu> menus = new LinkedList<Menu>();
        // 管理员显示所有菜单信息
        if ("admin".equals(user.getUsername())){
            menus = menuMapper.getAllMenusWithAdmin();
        }else{
            menus = menuMapper.getMenusByUserId(user.getUid());
        }
		return TreeUtils.getChildPerms(menus,"0");
	}*/
	
	
	//管理列表
	@Override
	public List<Menu> selectMenuList(Menu menu) {
       	List<Menu> menus= menuMapper.getAllMenus(menu);
        //新增和修改是选择父菜单
       	if("MC".equals(menu.getMenuType())||(menu.getMenuName()==null&&"".equals(menu.getMenuName()))) {
    		if(menus.size()<1) {
    			return null;
    		}	
    		for(Menu nd:menus) {
    			nd.setUrl(null);
    		}
    	//菜单名模糊查询
       	}else if(menu.getMenuName()!=null&&!"".equals(menu.getMenuName())){
       		List<Menu> rt= menuMapper.getAllMenus(menu);//查询结果
       		List<Menu> data=new ArrayList<Menu>();
       		for(Menu node:rt) {//循环获取每个查询结果节点的父节点，并传入下一个节点递归，最终获得一个新的结果集
       			data=getParentMenus(node.getMenuId(),data);
       		}
       		return data;
       	}
		return menus;
	}
	//递归获取所有父节点，并放入列表
	public List<Menu> getParentMenus(String nodeID,List<Menu> m){  
        //和数据库交互,得到当前节点记录  
    	Menu menu = menuMapper.getMenuById(nodeID);  
        if(menu != null){
        	if(!m.contains(menu)) {//没有这条数据 时才加入
        		m.add(menu);  
        	}
        	return getParentMenus(menu.getParentId(),m);  
        }else{  
            return m;  
        }  
	}
	
	@Override
	public List<Menu> getAllMenus2LoadTreeWithRoleId(String roleId) {
		List<Menu> menus=menuMapper.getAllMenus(new Menu());
		if(menus.size()<1) {
			return null;
		}
		List<Menu> mus=menuMapper.getMenusByRoleId(roleId);//已分配的权限
		for(Menu nd:menus) {
			if(mus.contains(nd)||"i".equals(nd.getMenuId())){//设置已有权限标识
				nd.setChecked(true);
			}
			nd.setUrl(null);
		}
		return menus;
	}

	
	@Override
	public Boolean changeMenusWithRoleId(String roleId, List<Menu> nodes) {
		String jsonStr=JSON.toJSONString(nodes);
		List<Menu> menus=JSON.parseObject(jsonStr,new TypeReference<List<Menu>>(){});
		ShrioUtil.clearCachedAuthorizationInfo();//删除用户对应菜单权限缓存
		//1.先删除该角色下所有菜单
		int n=menuMapper.removeMenusByRoleId(roleId);
		//2.再批量插入
		if(menus.size()>0) {
			HashMap<String, Object> map=new HashMap<>();
			map.put("roleId", roleId);
			map.put("menus", menus);
			menuMapper.saveBatchMenusWithRoleId(map);
		}
		return true;
	}

	@Override
	public Map<String,Object> moveUp(Menu menu) {
		Map<String,Object> map=new HashMap<>();
		//2.查询上级节点
		List<Menu> last=menuMapper.getLastoneMenu(menu.getMoveFlag(),menu.getParentId(),menu.getOrderNum());
		//1.判断是否能上移：ordernum是否为1
		if(last.size()==2) {
			String tmp=last.get(0).getOrderNum();
			last.get(0).setOrderNum(last.get(1).getOrderNum());
			last.get(1).setOrderNum(tmp);
			//批量更新:连接mysql的url上加 &allowMultiQueries=true 这个才可以执行
			ShrioUtil.clearCachedAuthorizationInfo();//删除用户对应菜单权限
			menuMapper.updateMenusByBatch(last);
			map.put("flag", true);
			map.put("msg", "移动成功");
		}else {//交换两条数据位置
			map.put("flag", false);
			if("up".equals(menu.getMoveFlag())){
				map.put("msg", "不能再上移");
			}else {
				map.put("msg", "不能再下移");
			}
		}
		return map;
	}

	@Override
	public Boolean removeMenuByMenuId(String menuId) {
		//取当前节点的所有兄弟节点，并按orderNum排序，删除后重新设置序号
		List<Menu> bro=menuMapper.getBrotherMenusByMenuId(menuId);
		//递归获取所有子节点
		String[] ids=getChildMenuIds(menuId,"").split(",");
		List<String> idlist=Arrays.asList(ids);
		ShrioUtil.clearCachedAuthorizationInfo();//删除用户对应菜单权限
		//删除本节点和子节点
		menuMapper.removeBatchMenusByIds(idlist);
		//删除角色权限表
		menuMapper.removeBatchRoleAndMenus(idlist);
		//重新排序
		for(int i=1;i<=bro.size();i++) {
			bro.get(i-1).setOrderNum(String.valueOf(i));
		}
		//批量更新
		int k=menuMapper.updateMenusByBatch(bro);
		//菜单前后序号更新
		return k==0?false:true;
	}
	
	
	//递归获取树当前节点及其子节点的主键
	private String getChildMenuIds(String id,String ids){
		if("".equals(ids)){
			ids=id;
		}
		List<String> childLists=this.getChildMenuByParentID(id);		
		if(childLists.size()>0){
			for(int i=0;i<childLists.size();i++){
				ids+=","+childLists.get(i);
				ids=getChildMenuIds(childLists.get(i), ids);
			}
		}
		return ids;
	}
	//根据父级id获取子节点
	private List<String> getChildMenuByParentID(String pid){
		return menuMapper.getChildMenuByParentID(pid);
	}
	
		@Override
		public Boolean saveMenu(Menu menu) {
			if(menu!=null) {
				ShrioUtil.clearCachedAuthorizationInfo();//删除用户对应菜单权限
				//如果排序编号不为最后需要更新的。。。。麻烦
				//根据父节点获取所有兄弟节点
				Boolean flag=false;
				List<Menu> bro=menuMapper.getBrotherMenusByParentId(menu.getParentId());
				//输入排序号小于兄弟节点个数：说明不在最后，兄弟节点需要重新排序
				if(!"".equals(menu.getOrderNum())&&Integer.valueOf(menu.getOrderNum())<bro.size()){
					//排序编号加0.5后保存
					menu.setOrderNum(String.valueOf(Integer.valueOf(menu.getOrderNum())-0.5));
				}else {
					menu.setOrderNum(String.valueOf(bro.size()+1));
				}
				flag=true;
				menu.setMenuId(UUIDUtil.getUUID());
				menu.setVisible("0");
				menuMapper.saveMenu(menu);//保存菜单
				//给管理员权限
				HashMap<String, Object> map=new HashMap<>();
				List<Menu> menus=new ArrayList<>();
				menus.add(menu);
				map.put("roleId", "6dc495ea67c4487d91f5d8967eab3780");
				map.put("menus", menus);
				menuMapper.saveBatchMenusWithRoleId(map);
				if(flag) {
					//再次取含兄弟节点的集合重新编号
					List<Menu> bro2=menuMapper.getBrotherMenusByParentId(menu.getParentId());
					//重新排序
					for(int i=1;i<=bro2.size();i++) {
						bro2.get(i-1).setOrderNum(String.valueOf(i));
					}
					//批量更新
					int k=menuMapper.updateMenusByBatch(bro2);
					//菜单前后序号更新
					return k==0?false:true;
				}
				return true;
			}
			return false;
		}

		@Override
		public Boolean editMenu(Menu menu) {
			Boolean flag=false;
			List<Menu> bro=menuMapper.getBrotherMenusByParentId(menu.getParentId());
			//输入排序号小于兄弟节点个数：说明不在最后，兄弟节点需要重新排序
			if(Integer.valueOf(menu.getOrderNum())<=bro.size()){
				//排序编号加0.5后保存
				menu.setOrderNum(String.valueOf(Integer.valueOf(menu.getOrderNum())-0.5));
			}else {
				menu.setOrderNum(String.valueOf(bro.size()+1));
			}
			flag=true;
			ShrioUtil.clearCachedAuthorizationInfo();//删除用户对应菜单权限
			menuMapper.editMenu(menu);
			if(flag) {
				//再次取含兄弟节点的集合重新编号
				List<Menu> bro2=menuMapper.getBrotherMenusByParentId(menu.getParentId());
				//重新排序
				for(int i=1;i<=bro2.size();i++) {
					bro2.get(i-1).setOrderNum(String.valueOf(i));
				}
				//批量更新
				int k=menuMapper.updateMenusByBatch(bro2);
				//菜单前后序号更新
				return k==0?false:true;
			}
			return true;
		}
		
		
	
}
